<?php
/*--------------------------------------------------------------------------

//echo '<pre>'; var_dump($this->arErrors); echo '</pre>';

 	$arForm = array
		(	'ID' 								=> 'form id',
			'NAME' 							=> 'form name',
			'TEMPLATE_PATH'			=> 'temlate server-side path',
			'MESSAGE'						=> 'initial form message',
			'SUCCESS_MSG'				=> 'if data valid show this string',
			'CUSTOM_CLASS' 			=> 'additional css class',
			'EMAIL_TO' 					=> 'receipient@mail.com',
			'POST_EVENT_NAME' 	=> 'event code',
			'IBLOCK_ID' 				=> 'iblock to save data',
			'IBLOCK_ELEMENT_SET_ACTIVE' => 'true/false',
			'USE_CAPTCHA' 			=> 'true/false', // Пока не реализовано
			'SUBMIT_STR'				=> 'submit button string'
		)
		
	$arFields = array
		(	0 => array
				(	'ID' 						=> 'Field id',	
					'NAME_FORM'			=> 'Field name in the form',
					'NAME_IBLOCK'		=> 'Field name in the infoblock',
					'NAME_PROP_IBLOCK' => 'Field name in the infoblock', 
					'NAME_EMAIL_EVENT' => 'Field name in the email event',
					'CONTENT_TYPE' 	=> 'text/numerical/email/password',
					'FIELD_TYPE' 		=> 'text/textarea/select/radiobtn', // Пока поддерживаются только текст и текстареа
					'REQUIRED' 			=> 'true/false',
					'REQUIRED_LENGHT'	=> 'minimal lenght',
					'VALIDATE_FAIL_MSG'	=> 'Не заполнено поле Field name',
					'COUNT_VALIDATE_FAIL_MSG' => 'Слишком короткий Field name',
					'FIELD_WIDTH' 	=> '0-shortest, 3-longest, max-99%',
					'CUSTOM_CLASS' 	=> 'additional css class',
					'REMARK_MSG' 		=> 'additional text for the field'
				)
		);
 */

class HTC_Simple_Forms
	{	private $arForm;
		private $arFields;
		private $arErrors;
		private $form_success;
		public $form_is_filled;
		
		function __construct($arForm, $arFields)
			{	$this->arForm = $arForm;
			
				/*
				 * Если в GET есть параметр [form_name]_success и он true
				 * сохраняем это значение в $form_success
				 */
				if ($_GET[$this->arForm['NAME'] . '_success'] = true)
					{	$this->form_success = true;
						return;
					}
				
				/*
				 * Для полей форм формируем html имена по имени поля в инфоблоке
				 */
				
				foreach ($arFields as $index=>$arField)
					{	if ($arField['NAME_IBLOCK']) $arFields[$index]['NAME_FIELD'] = $arField['NAME_IBLOCK'];
						else $arFields[$index]['NAME_FIELD'] = $arField['NAME_PROP_IBLOCK'];
					}
					
				$this->arFields = $arFields;
				
				/*
				 * если заполнена форма, устанавливаем флаг $form_is_filled,
				 * запускаем валидацию
				 */
				
				if ($_REQUEST[$this->arForm['NAME']])
					{	$this->form_is_filled = true;
						$this->Validate_Data();
						
						if (!$this->arErrors)
							{
								/*
								 * Если данные валидны, сохраняем данные в инфоблок и создаём почтовое событие
								 * иначе выводим форму с сообщениями об ошибках
								 */
								$this->Save_Data();
								LocalRedirect('?' . $this->arForm['NAME'] . '_success=true');
								return;
							}
					}
			}
			
		protected function Validate_Data() 
			{	if ($_REQUEST['antibot']) $this->arErrors[] = 'Заполнено поле, которое должно быть пустым!';
				foreach ($this->arFields as $arField)
					{	if ($arField['REQUIRED']) // проверяем, если поле обязательное, валидируем
							{	switch ($arField['CONTENT_TYPE'])
									{	case 'text':
										case 'textarea':
										case 'password':
											if (!$_REQUEST[$arField['NAME_FIELD']]) // проверяем на пустоту
												{	$this->arErrors[] = $arField['VALIDATE_FAIL_MSG'];
												}
											elseif ($arField['REQUIRED_LENGHT'] && strlen($_REQUEST[$arField['NAME_FIELD']]) >= $arField['REQUIRED_LENGHT']) // проверяем на длину
												{	$this->arErrors[] = $arField['COUNT_VALIDATE_FAIL_MSG'];
												}
											break;
										case 'email':
											if (!check_email($_REQUEST[$arField['NAME_FIELD']])) // проверяем емыл
												{	$this->arErrors[] = $arField['VALIDATE_FAIL_MSG'];
												}
											break;
										default:
											break;
									}	
							}
					};
			}
		
		protected function Save_Data() 
			{	/*
				 * Если задан IBLOCK_ID то сохраняем данные в него
				 */
				
				if ($this->arForm['IBLOCK_ID'])
					{	if (!CModule::IncludeModule("iblock"))
							{	die('Ошибка подключения модуля iblock');
							}

						$arIblock_Fields = array();
						$arIblock_Fields = array
							(	"IBLOCK_ID" => $this->arForm['IBLOCK_ID'],
								"ACTIVE" => $this->arForm['IBLOCK_ELEMENT_SET_ACTIVE'],
								"DATE_ACTIVE_FROM" => ConvertTimeStamp(getmicrotime(), "FULL")
							);
							
						/*
						 * Занесли данные из формы в массив для занесения в инфоблок
						 */
							
						foreach ($this->arFields as $arField)
							{	if ($arField['NAME_IBLOCK']) $arIblock_Fields[$arField['NAME_IBLOCK']] = trim($_REQUEST[$arField['NAME_FIELD']]);
								else $arIblock_Fields['PROPERTY_VALUES'][$arField['NAME_PROP_IBLOCK']] = trim($_REQUEST[$arField['NAME_FIELD']]);
							}
							
						/*
						 * Если не задано поле NAME, то элементу будет присвоено имя формы
						 */
							
						if (!$arIblock_Fields['NAME']) $arIblock_Fields['NAME'] = $this->arForm['NAME'];

						$element = new CIBlockElement;
						$result = $element->Add($arIblock_Fields);
						
						if (!$result) die('Ошибка создания элемента в инфоблоке №' . $this->arForm['IBLOCK_ID']);
					}
					
				/*
				 * Если задан символьный код почтового события, создаём его
				 */
					
				if ($this->arForm['POST_EVENT_NAME'])
					{	$eventParams = array();
					
						foreach ($this->arFields as $arField)
							{	
								/*
								 * Если не задано имя поля для почтового события, то это поле не будет включено в почтовое событие
								 */
								
								if ($arField['NAME_EMAIL_EVENT'])
									{	$eventParams[$arField['NAME_EMAIL_EVENT']] = trim($_REQUEST[$arField['NAME_FIELD']]);
									}
							}
							
						$eventParams['DATE'] = ConvertTimeStamp(getmicrotime(), "FULL");
						$post_event = CEvent::Send($this->arForm['POST_EVENT_NAME'], SITE_ID, $eventParams);
						if (!$post_event) die('Не удалось создать почтовое событие ' . $this->arForm['POST_EVENT_NAME']);
					}
			}
			
		public function Show_Form() 
			{	
				/*
				 * если форма уже заполнена и данные сохранены, выводим только сообщение об успехе
				 * иначе выводим форму
				 */
				if ($this->form_success) echo $this->arForm['SUCCESS_MSG'];
				else 
					{
						/*
						 * Если задан приветственный текст, выводим его
						 */
						
						if ($this->arForm['MESSAGE'])
							{	?>
								<p><?=$this->arForm['MESSAGE']?></p><?						
							}?>
						
						<form class="htc-simple-form needs-validation <?=$this->arForm['CUSTOM_CLASS']?>" method="post" action="" name="<?=$this->arForm['NAME']?>"><? 
							
							/*
							 * Если данные из формы не валидны, выводим ошибки
							 */
						
							if ($this->arErrors)
								{	?>
									<ul class="validate-errors"><?
										foreach ($this->arErrors as $error)
											{	?>
												<li><?=$error?></li><?
											}?>
									</ul><? 
								}?>
								
							<fieldset>
								<input type="hidden" name="<?=$this->arForm['NAME']?>" value="true"/>
								<input type="hidden" name="antibot" value=""/>
								<ul><? 
								foreach ($this->arFields as $arField)
									{	$li_class = '';
										$arField_class = array();
										$field_class = '';
																
										if ($arField['CUSTOM_CLASS'])
											{	$arField_class[] = $arField['CUSTOM_CLASS'];
											}
											
										/*
										 * Если поле обязательное, добавляем клиентскую валидацию
										 */
											
										if ($arField['REQUIRED'])
											{
												$li_class = ' class="htc-c-f-required"';
												/*
												 * В зависимости от типа данных в форме добавляем класс для скрипта клиентской валидации
												 */
													
												switch ($arField['CONTENT_TYPE'])
													{	case 'text':
															$arField_class[] = 'text-validation';
															break;
														case 'numerical':
															$arField_class[] = 'number-validation';
															break;
														case 'email':
															$arField_class[] = 'email-validation';
															break;
														default:
															break;
													}
											}
											
										/*
										 * Если задана ширина поля, присваиваем ему дополнительный css класс
										 */
											
										if ($arField['FIELD_WIDTH']) $arField_class[] = 'htc-s-f-width-' . $arField['FIELD_WIDTH'];
										
										/*
										 * Переводим список классов из массива в строку
										 */
										
										if ($arField_class)
											{	foreach ($arField_class as $class)
													{	if (!$field_class) $field_class = 'class="' . $class;
														else $field_class .= ' ' . $class;
													}
												$field_class .= '" ';
											}
										?>
										
										<li<?=$li_class?>>
											<dl>
												<dt>
													<label for="<?=$arField['NAME_FIELD']?>"><?=$arField['NAME_FORM']?></label><?
													
													/*
													 * Если есть текст в REMARK_MSG, вставляем её
													 */
													
													if ($arField['REMARK_MSG'])
														{	?>
															<span class="htc-s-f-remark"><?=$arField['REMARK_MSG']?></span><?
														}?>
												</dt>
												<dd><? 
													
													/*
													 * В зависимости от типа типа поля формируем разметку
													 */
												
													switch ($arField['FIELD_TYPE'])
														{	case 'text':
																?>
																<input <?=$field_class?>id="<?=$arField['NAME_FIELD']?>" type="text" name="<?=$arField['NAME_FIELD']?>" value="<?=trim($_REQUEST[$arField['NAME_FIELD']])?>" /><?
																break;
															case 'textarea':
																?>
																<textarea <?=$field_class?>id="<?=$arField['NAME_FIELD']?>" name="<?=$arField['NAME_FIELD']?>"><?=trim($_REQUEST[$arField['NAME_FIELD']])?></textarea><?
																break;
															default:
																break;
														}?>
												</dd>
											</dl>
										</li><?
									}?>
									<li>
										<dl>
											<dt></dt>
											<dd><input class="htc-s-f-btn" type="submit" name="submit" value="<?=$this->arForm['SUBMIT_STR']?>" /></dd>
										</dl>
									</li>
								</ul>
							</fieldset>
						</form><?
					}
			}
	}